home *** CD-ROM | disk | FTP | other *** search
- /*Copyright (c) 1993 Enterprise Integration Technologies Corporation
-
- Permission to use, copy, modify, distribute, and sell this software and
- its documentation for any purpose is hereby granted without fee, provided
- that (i) the above copyright notices and this permission notice appear in
- all copies of the software and related documentation, and (ii) the name of
- Enterprise Integration Technologies Corporation may not be used in any
- advertising or publicity relating to the software without the specific,
- prior written permission of Enterprise Integration Technologies Corporation.
-
- THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
- IN NO EVENT SHALL ENTERPRISE INTEGRATION TECHNOLOGIES CORPORATION BE
- LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF
- ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY
- THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
- */
- #include "dspd.h"
-
- int main(argc,argv)
- int argc;
- char **argv;
- {
- pid_t pid;
- strcpy(executable,MESH_PATH);
- gid=getegid();
- uid=geteuid();
- init();
- procopts(argc,argv);
- #ifdef USESYSLOG
- openlog("dsp",(LOG_PID | LOG_CONS),facility);
- #endif
- if(chdir(spooldir))
- {
- fprintf(stderr,"dspd: Invalid spool directory.\n");
- exit(1);
- }
- /*Now become a daemon*/
- if((rund)&&daemonize())
- {
- fprintf(stderr,"Unable to become a daemon. Aborting.\n");
- exit(2);
- }
- writepid();
- signal(SIGUSR1,sighalt);
- mainloop();
- #ifdef USESYSLOG
- syslog(facility | LOG_ALERT,"My work here is done.");
- #endif
- delpid();
- exit(0);
- }
-
- int daemonize() /*This function modeled closely after Stevens*/
- {
- pid_t pid;
-
- if((pid=fork())<0)
- return(-1);
- if(pid!=0)
- exit(0);
-
- setsid();
- umask(0);
- return(0);
- }
-
- int procopts(argc,argv)
- int argc;
- char **argv;
- {
- int ret;
- while((ret=getopt(argc,argv,"q:s:k:d:m:bQ:t:p:e:l:n"))!=-1)
- {
- switch(ret)
- {
- case 's':
- if((ret=strtosecs(optarg))!=-1)
- sleepwhenempty=ret;
- break;
- case 'q':
- if((ret=strtosecs(optarg))!=-1)
- queuetime=ret;
- break;
- case 'k':
- if((ret=strtosecs(optarg))!=-1)
- killtime=ret;
- break;
- case 'd':
- if(strlen(optarg)>MAXPATHLEN)
- {
- fprintf(stderr,"Invalid spool path--too long\n");
- exit(1);
- }
- else
- strcpy(spooldir,optarg);
- break;
- case 'e':
- if(strlen(optarg)>MAXPATHLEN)
- {
- fprintf(stderr,"Invalid program--path too long\n");
- exit(1);
- }
- else
- strcpy(executable,optarg);
- break;
- case 'b':
- rund=1;
- break;
- case 'm':
- if((ret=strtosecs(optarg))!=-1)
- maxmeshes=(ret>MAX_MESHES)?MAX_MESHES:ret;
- break;
- case 'Q':
- if((ret=strtosecs(optarg))!=-1)
- queuesize=(ret>QUEUESIZE)?QUEUESIZE:ret;
- break;
- case 't':
- if((ret=strtosecs(optarg))!=-1)
- timeval=ret;
- break;
- case 'p':
- if((ret=strtosecs(optarg))!=-1)
- prival=ret;
- break;
- case 'l':
- switch(atoi(optarg))
- {
- case '0': facility=LOG_LOCAL0;
- break;
- case '1': facility=LOG_LOCAL1;
- break;
- case '2': facility=LOG_LOCAL2;
- break;
- case '3': facility=LOG_LOCAL3;
- break;
- case '4': facility=LOG_LOCAL4;
- break;
- case '5': facility=LOG_LOCAL5;
- break;
- case '6': facility=LOG_LOCAL6;
- break;
- case '7': facility=LOG_LOCAL7;
- break;
- }
- logfac=atoi(optarg);
- break;
- case 'n': nounlink=1;
- break;
- case '?':
- fprintf(stderr,"dspd: dspd [-qtime] [-stime]\n");
- exit(1);
- default:
- break;
- }
- }
- }
-
- strtosecs(arg)
- char *arg;
- {
- int units,last,time;
- char *foo;
-
- switch(arg[last=(strlen(arg)-1)]) {
- case 'h':
- units=3600;
- arg[last]='\0';
- break;
- case 'm':
- units=60;
- arg[last]='\0';
- break;
- case 's':
- units=1;
- arg[last]='\0';
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- units=1;
- break;
- default:
- return(-1);
- break;
- }
-
- if((!(time=strtol(arg,&foo,10)))&&(foo==arg))
- return(-1);
- time*=units;
- return(time);
- }
-
- mainloop()
- {
- int test;
- while(1)
- {
- if((totalmsgs=queuemsgs())>0)
- procmsgs();
- else
- {
- meshreap();
- if(!meshes)
- {
- if(sleepwhenempty)
- sleep(sleepwhenempty);
- else
- return;
- }
- }
- if(halt && (!meshes))
- return;
- }
- }
-
- queuemsgs()
- {
- DIR *dirp;
- static struct dirdat msglist[QUEUESIZE];
- struct dirent *p;
- static struct dirdat p2;
- struct dirdat *new,*potential=&p2;
- int sz,size=0;
- register int j,k,l;
-
- if(!(dirp=opendir(spooldir)))
- error(E_OPENDIR,spooldir);
-
- /*We use a fixed size priority queue to get the best n elements...*/
- while(p=readdir(dirp))
- {
- strcpy(potential->d_name,p->d_name);
- if((!readok(potential))||beingprocessed(potential))
- continue;
- if(size<(queuesize-1))
- {
- memcpy((char *)&msglist[++size],(char *)potential,sizeof(struct dirdat));
- msgplist[size]=msglist+size;
- j=size;
- while((j!=1)&&(nicecmp(msgplist[j/2],potential)<=0))
- {
- msgplist[j]=msgplist[j/2];
- j/=2;
- }
- msgplist[j]=msglist+size;
- }
- else
- {
- if(nicecmp(msgplist[1],potential)<0)
- continue;
- /*Swap contents w/ nicest value--then reheap*/
- memcpy((char *)msgplist[1],(char *)potential,sizeof(struct dirdat));
- new=msgplist[1];
- DOWNHEAP;
- }
- }
-
- sz=size;
- for(l=size;l>0;)
- {
- new=msgplist[1];
- msgplist[1]=msgplist[l];
- msgplist[l--]=new;
- size--;
- new=msgplist[1];
- DOWNHEAP;
- }
- closedir(dirp);
- nextscanat=time((time_t *)NULL)+queuetime;
- return(sz);
- }
-
- nicecmp(d1,d2)
- struct dirdat *d1,*d2;
- {
- int p1,p2;
- p1=(*(d1->d_name))*prival+(d1->buf.st_mtime)*timeval;
- p2=(*(d2->d_name))*prival+(d2->buf.st_mtime)*timeval;
- if(p1==p2)
- return(0);
- if(p1<p2)
- return(1);
- return(-1);
- }
-
- procmsgs()
- {
- int mesh,lastmesh;
- time_t killtime;
- int msgs=1;
-
- while((msgs<=totalmsgs)&&(time((time_t *)NULL)<nextscanat))
- {
- for(mesh=0;(mesh<maxmeshes)&&(msgs<=totalmsgs);mesh++)
- {
- time_t age,tolive;
- if(!procdata[mesh].pid)
- if((!halt)&&meshstart(mesh,msgs))
- msgs++;
- else
- continue;
-
- age=time((time_t *)NULL)-procdata[mesh].starttime;
- if(age>killtime)
- meshkill(mesh);
- }
- meshreap();
- if((!meshes)&&(halt))
- return;
- if((meshes==maxmeshes)||halt)
- {
- timewait();
- meshreap();
- }
- }
- }
-
- meshreap()
- {
- int status;
- struct rusage usage;
- pid_t pid;
- while(pid=wait3(&status,WNOHANG,&usage))
- {
- if(pid>0)
- meshclean(pid,status,usage);
- else
- {
- if(errno==EINTR)
- continue;
- if(errno==ECHILD)
- return(0);
- error(E_WAIT,NULL);
- }
- }
- }
-
- timewait()
- {
- int mesh;
- time_t earliest,atime,now,when;
- pid_t pid;
- int first;
- int status;
- struct rusage usage;
-
- earliest=time((time_t *)NULL);
- for(mesh=0;mesh<maxmeshes;mesh++)
- {
- if(!(procdata[mesh].pid))
- continue;
-
- if(earliest>(procdata[mesh].starttime))
- {
- first=mesh;
- earliest=procdata[mesh].starttime;
- }
- }
-
- signal(SIGALRM,sigbogo);
- #ifdef USESIGINTERRUPT
- siginterrupt(SIGALRM,1);
- #endif
-
- now=time((time_t *)NULL);
- if((now-earliest)>killtime)
- atime=0;
- else
- atime=killtime-(now-earliest);
-
- when=time((time_t *)NULL)+atime;
- alarm(atime);
-
- if((pid=wait3(&status,0,&usage))<0)
- {
- now=time((time_t *)NULL);
- if((errno==EINTR)&&(now>=when))
- {
- meshkill(first);
- return;
- }
- else
- {
- error(E_WAIT,NULL);
- if(errno==ECHILD)
- for(mesh=0;mesh<maxmeshes;mesh++)
- procdata[mesh].pid=0;
- return;
- }
- }
- meshclean(pid,status,&usage);
- }
-
- meshstart(mesh,msg)
- int mesh;
- int msg;
- {
- pid_t pid;
- char out[1024];
-
- strcpy(procdata[mesh].d_name,msgplist[msg]->d_name);
- #ifndef USEVFORK
- if((pid=fork())<0)
- #else
- if((pid=vfork())<0)
- #endif
- {
- error(E_NOFORK,NULL);
- return(0);
- }
-
- if(pid==0) /*Child*/
- {
- char logflag[4];
- sprintf(out,"Started processing of %s",msgplist[msg]->d_name);
- #ifdef USESYSLOG
- syslog(NORM_LEVEL | facility,out);
- #endif
- sprintf(logflag,"-l%d",logfac);
- execlp(executable,executable,logflag,msgplist[msg]->d_name,(char *)0);
- error(E_NOEXEC,executable);
- _exit(1);
- }
- else /*parent*/
- {
- procdata[mesh].pid=pid;
- procdata[mesh].starttime=time((time_t *)NULL);
- meshes++;
- }
- return(1);
- }
-
- meshkill(mesh)
- int mesh;
- {
- char out[1024];
-
- sprintf(out,"Processing of %s timed out. ",procdata[mesh].d_name);
- if(kill(procdata[mesh].pid,SIGTERM))
- {
- error(E_NOKILL,procdata[mesh].d_name);
- sprintf(out+strlen(out),"\nTried to kill but failed. ");
- }
- else
- sprintf(out+strlen(out,"\nTerminated w/ extreme prejudice. "));
-
- if(!nounlink)
- {
- if(unlink(procdata[mesh].d_name)&&(errno!=ENOENT))
- {
- error(E_UNLINK,procdata[mesh].d_name);
- sprintf(out+strlen(out),"File removal failed.");
- }
- else
- sprintf(out+strlen(out),"File removed.");
- }
-
- syslog(NORM_LEVEL,out);
- meshreap();
- }
-
- meshclean(pid,status,rusage)
- pid_t pid;
- int status;
- struct rusage *rusage;
- {
- int mesh;
- char out[1024];
-
- for(mesh=0;mesh<maxmeshes;mesh++)
- if(procdata[mesh].pid==pid) break;
-
- meshes--;
- if(halt)
- logstat();
- procdata[mesh].pid=0;
- #ifdef USESYSLOG
- if(status)
- sprintf(out,"Processing seems to have failed on [%d] %s. Exit status %d",
- pid,procdata[mesh].d_name,status);
- else
- sprintf(out,"Processing seems to have terminated normally on [%d] %s",
- pid,procdata[mesh].d_name);
- syslog(NORM_LEVEL,out);
- sprintf(out,"%s used User time: %ld.%ld, System time: %ld.%ld ",
- procdata[mesh].d_name,
- rusage->ru_utime.tv_sec,rusage->ru_utime.tv_usec,
- rusage->ru_stime.tv_sec,rusage->ru_stime.tv_usec);
- syslog(NORM_LEVEL,out);
- #endif
- if(!nounlink)
- if(unlink(procdata[mesh].d_name))
- {
- if(errno!=ENOENT)
- error(E_EXISTS,procdata[mesh].d_name);
- }
- }
-
- beingprocessed(d)
- struct dirdat *d;
- {
- int mesh;
- for(mesh=0;mesh<maxmeshes;mesh++)
- {
- if(procdata[mesh].pid)
- {
- if(!strcmp(procdata[mesh].d_name,d->d_name))
- return(1);
- }
- }
- return(0);
- }
-
- readok(d)
- struct dirdat *d;
- {
- struct stat buf;
-
- if(*(d->d_name)=='.')
- return(0);
- if(!strcmp(d->d_name,"core"))
- return(0);
- if(stat(d->d_name,&buf))
- {
- error(E_STAT,d->d_name);
- return(0);
- }
- memcpy((char *)&(d->buf),(char *)&buf,sizeof(buf));
- if(!(S_ISREG(buf.st_mode)))
- return(0);
-
- if(uid==buf.st_uid)
- {
- if(buf.st_mode&S_IRUSR)
- return(1);
- else
- return(0);
- }
- if(gid==buf.st_gid)
- {
- if(buf.st_mode&S_IRGRP)
- return(1);
- else
- return(0);
- }
- if(buf.st_mode&S_IROTH)
- return(1);
- else
- return(0);
- }
-
- error(e,c)
- int e;
- char *c;
- {
- char line[1024];
-
- strcpy(line,err[e].msg);
- if(c)
- strcat(line,c);
- if(err[e].status & SYSTEM)
- strcat(line," because %m");
- #ifdef USESYSLOG
- syslog(facility | err[e].level,line);
- #endif
- if(err[e].status & FATAL)
- {
- delpid();
- exit(1);
- }
- }
-
- sigbogo(signo)
- int signo;
- {
-
- /*bogo func...*/
- }
- sighalt(signo)
- int signo;
- {
- char out[1024];
- sleepwhenempty=0;
- halt=1;
- sprintf(out,"Halt signal caught. Preparing to shutdown.");
- #ifdef USESYSLOG
- syslog(LOG_ALERT | facility,out);
- #endif
- logstat();
- }
-
- logstat()
- {
- char out[1024];
- sprintf(out,"%d subprocesses still running. ");
- if(meshes)
- strcat(out,"I think I can. I think I can.",meshes);
- else
- strcat(out,"I thought I could. I thought I could.");
- #ifdef USESYSLOG
- syslog(LOG_ALERT | facility,out);
- #endif
- }
-
- init()
- {
- int mesh;
- for(mesh=0;mesh<maxmeshes;mesh++)
- procdata[mesh].pid=0;
- }
-
- writepid()
- {
- FILE *fp;
- pid_t pid;
- char *h;
- char buf[MAXPATHLEN+1];
- char *getenv();
-
- pid=getpid();
-
- if(fp=fopen(PIDFILE,"w"))
- fprintf(fp,"%d\n",pid);
- else
- error(E_NOPID,NULL);
- fclose(fp);
- }
-
- delpid()
- {
- char buf[MAXPATHLEN+1];
- char *getenv();
- char *h;
-
- if(unlink(PIDFILE)<0)
- error(E_STILLPID,NULL);
- }
-
-
-
-
-
-
-
-
-
-